In [1]:
import sys
import os
sys.path.insert(0, os.path.abspath('../'))
sys.path.insert(0, os.path.abspath('../../'))
sys.path.insert(0, os.path.abspath('/home/hm-tlacherm/qlm_notebooks/notebooks_1.2.1/notebooks/master_thesis_qaoa/'))
sys.path.insert(0, os.path.abspath('/home/hm-tlacherm/qlm_notebooks/notebooks_1.2.1/notebooks/master_thesis_qaoa/ibm/'))
In [2]:
import numpy as np

import qiskit
provider = qiskit.IBMQ.load_account()
from qiskit import Aer
from qiskit.utils import QuantumInstance
from qiskit_optimization.algorithms import MinimumEigenOptimizer
from qiskit.algorithms import QAOA
from shared.QiskitMaxcut import *
from ibm.ibm_parameters import *

from matplotlib import pyplot as plt
%matplotlib inline
In [3]:
graph = load_nx_graph_from("/home/hm-tlacherm/qlm_notebooks/notebooks_1.2.1/notebooks/master_thesis_qaoa/data/graphs/16_nodes/graph_16_33_01_w.txt")
max_cut = Maxcut(graph)
max_cut_qubo = max_cut.to_qubo()
print(graph.name)
max_cut.draw()
graph_16_33_01_w
In [4]:
step_size = 0.1
a_gamma = np.arange(0, np.pi, step_size)
b_beta = np.arange(0, np.pi, step_size)
In [5]:
a_gamma, b_beta = np.meshgrid(a_gamma, b_beta)
In [6]:
quantum_instance = QuantumInstance(
                    backend=Aer.get_backend(DEFAULT_QASM_SIMULATOR),
                    shots=SHOTS)
qaoa = QAOA(
            optimizer=COBYLA(maxiter=0),
            quantum_instance=quantum_instance,
            reps=1
            )

op, offset = max_cut_qubo.to_ising()
In [7]:
def maxcut_obj(x, G):
    """
    Given a bitstring as a solution, this function returns
    the number of edges shared between the two partitions
    of the graph.
    
    Args:
        x: str
           solution bitstring
           
        G: networkx graph
        
    Returns:
        obj: float
             Objective
    """
    obj = 0
    for i,j,w in graph.edges.data('weight'):
        if x[i] != x[j]:
            obj -= w
            
    return obj


def compute_expectation(counts, G):
    
    """
    Computes expectation value based on measurement results
    
    Args:
        counts: dict
                key as bitstring, val as count
           
        G: networkx graph
        
    Returns:
        avg: float
             expectation value
    """
    
    avg = 0
    sum_count = 0
    for bitstring, count in counts.items():
        
        obj = maxcut_obj(bitstring, G)
        avg += obj * count
        sum_count += count
        
    return avg/sum_count
In [8]:
def create_cirucit(gamma,beta):
    circuits = qaoa.construct_circuit([gamma,beta], operator=op)
    circuit = circuits[0]
    circuit.measure_all()
    return circuit
In [9]:
landscape = np.zeros(a_gamma.shape)

for i in range(0, len(landscape)):
    circuits = []
    for j in range(0, len(landscape)):
        # create circuits for entire row 
        circuit = create_cirucit(a_gamma[i][j], b_beta[i][j])
        circuits.append(circuit)
    
    # create one job with circuits 
    job_name = f"{graph.name}_row_{i}"
    job = qiskit.execute(circuits, backend=provider.get_backend('ibmq_toronto'), shots=8000)
    job.update_name(job_name)
    print(job_name)
    
    # add results to landscape 
    j = 0
    for count in job.result().get_counts():
        mean = compute_expectation(count, graph)
        landscape[i,j] = mean
        j += 1
graph_16_33_01_w_row_0
graph_16_33_01_w_row_1
graph_16_33_01_w_row_2
graph_16_33_01_w_row_3
graph_16_33_01_w_row_4
graph_16_33_01_w_row_5
graph_16_33_01_w_row_6
graph_16_33_01_w_row_7
graph_16_33_01_w_row_8
graph_16_33_01_w_row_9
graph_16_33_01_w_row_10
graph_16_33_01_w_row_11
graph_16_33_01_w_row_12
graph_16_33_01_w_row_13
graph_16_33_01_w_row_14
graph_16_33_01_w_row_15
graph_16_33_01_w_row_16
graph_16_33_01_w_row_17
graph_16_33_01_w_row_18
graph_16_33_01_w_row_19
graph_16_33_01_w_row_20
graph_16_33_01_w_row_21
graph_16_33_01_w_row_22
graph_16_33_01_w_row_23
graph_16_33_01_w_row_24
graph_16_33_01_w_row_25
graph_16_33_01_w_row_26
graph_16_33_01_w_row_27
graph_16_33_01_w_row_28
graph_16_33_01_w_row_29
graph_16_33_01_w_row_30
graph_16_33_01_w_row_31
In [10]:
print(landscape)
plt.matshow(landscape)
plt.show()
[[-88.023875 -87.076875 -86.179125 ... -89.13625  -88.588    -87.7965  ]
 [-84.574    -84.6205   -85.36975  ... -85.623625 -85.3655   -84.745375]
 [-83.914625 -84.307    -85.134125 ... -84.767875 -83.712    -83.79525 ]
 ...
 [-83.22975  -83.504375 -83.781125 ... -84.66175  -83.656125 -82.947375]
 [-83.7175   -83.650375 -83.855    ... -84.869875 -84.388875 -83.5155  ]
 [-83.859125 -83.214375 -83.555    ... -85.17125  -84.809875 -83.444625]]
In [11]:
# Mean of landscape
np.mean(landscape)
Out[11]:
-86.40456164550781
In [12]:
# Minimium 
np.min(landscape)
Out[12]:
-90.045125
In [13]:
# Display Coordinates of Minimum 
np.unravel_index(np.argmin(landscape), landscape.shape)
Out[13]:
(0, 27)
In [14]:
# Gamma and beta value of Minimium
gamma, beta = np.unravel_index(np.argmin(landscape), landscape.shape)
opt_gamma = gamma * step_size
opt_beta = beta * step_size
print(f"Opt.Gamma: {opt_gamma}, Opt.Beta: {opt_beta}")
Opt.Gamma: 0.0, Opt.Beta: 2.7
In [15]:
# Save result matrix 
with open('landscape_toronto_paper_weights_results.npy', 'wb') as f:
    np.save(f, landscape)
In [16]:
import plotly.graph_objects as go
In [17]:
# Plot landscape in 3D 
a_gamma = np.arange(0, np.pi, step_size)
b_beta = np.arange(0, np.pi, step_size)
fig = go.Figure(data=go.Surface(z=landscape, x=a_gamma, y=b_beta))

fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor='limegreen', project_z=True))


fig.update_layout(title="QAOA MaxCut", scene=dict(
    xaxis_title="gamma",
    yaxis_title="beta",
    zaxis_title="mean"
))
In [18]:
# Plot Heatmap 
fig = go.Figure(data=go.Heatmap(z=landscape, x=b_beta, y=a_gamma, type = 'heatmap', colorscale = 'viridis'))

# Update Layout
fig.update_layout(title="QAOA MaxCut", width=700, height=700, xaxis_title="beta", yaxis_title="gamma")

# Display Global Minimium 
fig.add_trace(
    go.Scatter(mode="markers", x=[opt_beta], y=[opt_gamma], marker_symbol=[204], text = [landscape[gamma,beta]],
                   marker_color="red",  hovertemplate="x: %{x}<br>y: %{y}<br> z: %{text:.2f}<extra></extra>", 
                   marker_line_width=1, marker_size=16))
In [19]:
# Display Optimizer Results

# Display path 
#fig.add_trace(
#    go.Scatter(mode="lines", x=gammas, y=betas, marker_symbol=[200],
#                   marker_color="white", marker_line_width=1, marker_size=8)
#)

# Display start point
#fig.add_trace(
#    go.Scatter(mode="markers", x=[gammas[0]], y=[betas[0]], marker_symbol=[204],
#                   marker_color="gray", 
#                   marker_line_width=1, marker_size=16))

# Display end point
#fig.add_trace(
#    go.Scatter(mode="markers", x=[gammas[-1]], y=[betas[-1]], marker_symbol=[204],
#                   marker_color="green", 
#                   marker_line_width=1, marker_size=16))
In [20]:
# Plot Optimizer History
#fig = go.Figure(data=go.Scatter(x=counts, y=values))
#fig.update_layout(xaxis_title="Evaluation Counts", yaxis_title="Evaluated Mean", title="Optimizer")
#fig.show()
In [ ]: